﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Clandestine;
using System.Drawing;
using Slick.MapEditor.Tools;

namespace Slick.MapEditor.Tools
{
    public delegate void ToolHandler(int mouseX, int mouseY, int tileX, int tileY);

    public enum Mode
    {
        PaintTiles,
        AddEntity,
        SelectEntity,
        Selection
    }

    public class ToolController
    {
        public Map Map;
        public Dictionary<Mode, ITool> Tools = new Dictionary<Mode, ITool>();
        public ITool CurrentTool = null;

        private Point mousePosition = new Point();

        public ToolController(Map map)
        {
            this.Map = map;

            // Add tools
            Tools.Add(Mode.PaintTiles, new TilePainter(map));
            Tools.Add(Mode.AddEntity, new EntityAdder(map));
            Tools.Add(Mode.SelectEntity, new EntitySelecter(map));
            Tools.Add(Mode.Selection, new Selection(map));
            CurrentTool = Tools[0]; // TilePainter ;)
        }

        public void SetMode(Mode mode)
        {
            try
            {
                CurrentTool = this.Tools[mode];
                Map.Layers.ResetTempLayer();
            }
            catch (Exception e)
            {
                Log.e("Tried changing tool to {0} but failed. Does that tool exist/is it loaded?", mode.ToString());
            }
        }

        public void MouseButtonCallback(int button, int down)
        {
            // Pressed down?
            if (down == 1)
            {
                // Left?
                if (button == 0)
                    callHandler(CurrentTool.MouseDownLeft, mousePosition.X, mousePosition.Y);
                else // otherwise, right
                    callHandler(CurrentTool.MouseDownRight, mousePosition.X, mousePosition.Y);
            }
            else // not pressed down
            { 
                // Left?
                if (button == 0)
                    callHandler(CurrentTool.MouseUpLeft, mousePosition.X, mousePosition.Y);
                else // otherwise, right
                    callHandler(CurrentTool.MouseUpRight, mousePosition.X, mousePosition.Y);
            }
        }

        public void MousePositionCallback(int x, int y)
        {
            // Remember the position as we don't get given it for button callbacks
            mousePosition = new Point(x, y);

            // do our callback
            callHandler(CurrentTool.MouseMove, x, y);
        }

        private void callHandler(ToolHandler func, int x, int y)
        {
            // Get mouse x and y w.r.t. the camera zoom and position
            int mouseX = (int)((x / Camera.Zoom) + Camera.Position.X);
            int mouseY = (int)((y / Camera.Zoom) + Camera.Position.Y);

            // Get tile positions
            int tileX = ((int)(x / Camera.Zoom + Camera.Position.X)) / Program.GridSize;
            int tileY = ((int)(y / Camera.Zoom + Camera.Position.Y)) / Program.GridSize;

            func(mouseX, mouseY, tileX, tileY);
        }
    }
}
